package org.xtext.runtime.lang;

import java.util.Scanner;

import org.xtext.runtime.interpreter.ActionParam;
import org.xtext.runtime.library.Library;

public class System extends Library {
	static Scanner input = new Scanner(java.lang.System.in);
	
	/**
	 * This is analogous to System.out.println
	 * 
	 * @param message
	 * @return
	 */
	@ACTION
	public boolean println(String message) {
		java.lang.System.out.println("[" + agent.name() + "] " + message);
		return true;
	}
	
	/**
	 * This is analogous to System.out.println
	 * 
	 * @param message
	 * @return
	 */
	@ACTION
	public boolean print(String message) {
		java.lang.System.out.print("[" + agent.name() + "] " + message);
		return true;
	}
	
	@ACTION
	public boolean skip() {
		return true;
	}
	
	@TERM
	public String name() {
		return agent.name();
	}
	
	@ACTION
	public boolean sleep(long time) {
		try {
			Thread.sleep(time);
		} catch (InterruptedException e) {
			return false;
		}
		return true;
	}
	
	@ACTION
	public boolean fail() {
		return false;
	}

	/**
	 * Terminates the agent.
	 * 
	 * @return
	 */
	@ACTION
	public boolean terminate() {
		agent.terminate(true);
		return true;
	}
	
	
	/**
	 * Shuts down the runtime by invoking java.lang.System.exit(0).
	 * 
	 * @return
	 */
	@ACTION
	public boolean exit() {
		java.lang.System.exit(0);
		return true;
	}
	
	/**
	 * This method represents the action of reading a single integer from the user through
	 * the standard input. If the integer is entered correctly a belief is added to the agent
	 * with the value of the integer the belief is of the form "readInteger(int value)".
	 * If there is a problem with the input of the integer the method returns false, ie the action fails
	 * and no belief is added.
	 * @return true if the action succeeds; false otherwise.
	 */
	@ACTION
	public boolean readInt(ActionParam<Integer> param){
		try{
			int i = input.nextInt();
			param.set(i);
		} catch (Exception e){
			return false;
		}
		return true;
	}
	
	/**
	 * This method represents the action of reading a single long from the user through
	 * the standard input. If the long is entered correctly a belief is added to the agent
	 * with the value of the long the belief is of the form "readLong(long value)".
	 * If there is a problem with the input of the long the method returns false, ie the action fails
	 * and no belief is added.
	 * @return true if the action succeeds; false otherwise.
	 */
	@ACTION
	public boolean readLong(ActionParam<Long> param){
		try{
			long i = input.nextLong();	
			param.set(i);
		} catch (Exception e){
			return false;
		}
		return true;
	}
	
	
	/**
	 * This method represents the action of reading a single double from the user through
	 * the standard input. If the double is entered correctly a belief is added to the agent
	 * with the value of the double the belief is of the form "readLong(double value)".
	 * If there is a problem with the input of the double the method returns false, ie the action fails
	 * and no belief is added.
	 * @return true if the action succeeds; false otherwise.
	 */
	@ACTION
	public boolean readDouble(ActionParam<Double> param){
		try{
			double i = input.nextDouble();	
			param.set(i);
		} catch (Exception e){
			return false;
		}
		return true;
	}
	
	/**
	 * This method represents the action of reading a single word from the user through
	 * the standard input. If the String is entered correctly a belief is added to the agent
	 * with the value of the word the belief is of the form "readLong(string value)".
	 * If there is a problem with the input of the word the method returns false, ie the action fails
	 * and no belief is added.
	 * @return true if the action succeeds; false otherwise.
	 */
	@ACTION
	public boolean readWord(ActionParam<String> param){
		try{
			String i = input.next();
			param.set(i);
		} catch (Exception e){
			return false;
		}
		return true;
	}
	
	
}
